#include <pthread.h>
#include <vector>
#include <iostream>
#include <mutex>
#include "sem.hpp"
namespace ring_queue_module
{
    using namespace sem_module;
    const size_t DEFAULT_CAPACITY = 1000;
    template<class T>
    class ring_queue
    {
    public:
        ring_queue(size_t max_size = DEFAULT_CAPACITY)
            :_r_queue(max_size)
            ,_max_size(max_size)
            ,_space_count(0, max_size)
            ,_data_count(0, 0)
            ,_begin(0)
            ,_end(0)
        {}

        void push(const T& val)
        {
            //只要_space_count为0就阻塞等待
            //_space_count为0表示没有空闲空间
            int err = _space_count.wait();
            //错误处理(日志)
            //...
            {
                //在信号量等待后再加锁
                //以便自己加锁期间，其他线程也能够访问信号量
                std::lock_guard<std::mutex> lock(_producer_mutex);
                
                _r_queue[_end] = val;
                std::cout << "生产数据 " << val << std::endl;
                _end = (_end + 1) % _max_size;
                
            }
            //生产者生产了一个数据，数据计数原子加1
            err = _data_count.post();
            //错误处理(日志)
            //...
        }

        const T& pop()
        {
            //只要_data_count为0就阻塞等待
            //_data_count为0表示没有数据
            int err = _data_count.wait();
            //错误处理(日志)
            //...
            {
                //在信号量等待后再加锁
                //以便自己加锁期间，其他线程也能够访问信号量
                std::lock_guard<std::mutex> lock(_consumer_mutex);
                T& ret = _r_queue[_begin];
                std::cout << "消费数据 " << ret << std::endl;
                _begin = (_begin + 1) % _max_size;
            }

            //消费者消费了一个数据，空闲空间计数原子加1
            err = _space_count.post();
            //错误处理(日志)
            //...
            return ret;
        }

    private:
        std::vector<T> _r_queue;         //环形队列底层容器
        size_t _max_size;                //环形队列最大容量
        sem _space_count;                //空闲空间计数
        sem _data_count;                 //数据计数
        std::mutex _producer_mutex;      //生产者互斥锁
        std::mutex _consumer_mutex;      //消费者互斥锁
        int _begin;                      //环形队列头指针
        int _end;                        //环形队列尾指针
    };
}